Tidak dapat menguraikan nama dari halaman ketiga dan seterusnya

Saya telah membuat skrip dengan python menggunakan modul permintaan dan perpustakaan BeautifulSoup untuk mengambil nama anggota yang berbeda dari situs web. Script dapat mengambil nama dari halaman pertama dan halaman kedua dengan sempurna. Namun, ia menghapus nama yang sama dari halaman ketiga dan seterusnya. Apa yang saya perhatikan adalah logika halaman berikutnya berada dalam nilai __EVENTTARGET, seperti pada dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl07 dan dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl09 dan seterusnya. Skrip dapat menambah angka sesuai tetapi hasil setelah halaman kedua tetap sama.

Untuk mengisi hasil dari situs web, yang perlu Anda lakukan hanyalah mengklik tombol pencarian tanpa mengubah apa pun. Anda kemudian dapat mengklik halaman 2,3,4 e.t.c untuk melanjutkan ke halaman terkait.

Saya sudah mencoba dengan (mengikis data dari dua halaman pertama):

import requests
from bs4 import BeautifulSoup

link = 'https://www.icsi.in/student/Members/MemberSearch.aspx?SkinSrc=%5BG%5DSkins/IcsiTheme/IcsiIn-Bare&ContainerSrc=%5BG%5DContainers/IcsiTheme/NoContainer'

with requests.Session() as s:
    s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
    r = s.get(link)
    soup = BeautifulSoup(r.text,"lxml") 
    payload = {i['name']:i.get('value','') for i in soup.select('input[name]')}
    payload['__EVENTTARGET'] = 'dnn$ctr410$MemberSearch$btnSearch'

    page = 5
    while True:
        r = s.post(link,data=payload)
        soup = BeautifulSoup(r.text,"lxml")
        for item in soup.select("span[id$='_lblFullName']"):
            print(item.text)

        page+=2
        payload = {i['name']:i.get('value','') for i in soup.select('input[name]')}
        if len(str(page))==1:
            payload['__EVENTTARGET'] = 'dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl0{}'.format(page)
        else:
            payload['__EVENTTARGET'] = 'dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl{}'.format(page)

        payload['__dnnVariable'] = {'__scdoff':'1','__dnn_pageload':'__dnn_setScrollTop();'}
        payload['ScrollTop'] = '400'

Bagaimana cara mengambil nama dari halaman lainnya setelah halaman kedua?


person MITHU    schedule 11.05.2020    source sumber
comment
sepertinya halaman ASP.NET - dapat mengirim banyak nilai POST - tidak hanya __EVENTTARGET - dan Anda mungkin harus mengirim semuanya - juga sebagai permintaan POST. PERTAMA: gunakan DevTools di Firefox/Chrome untuk melihat semua permintaan yang dikirim dari browser saat Anda membuka halaman berikutnya - dan lihat nilai apa yang dikirimkannya, dan apakah itu permintaan GET atau POST. Kode Anda harus mengirimkan hal yang sama.   -  person furas    schedule 11.05.2020
comment
Saya mungkin mengirimkan semuanya. Jika Anda mencetak payload, Anda dapat melihat parameter yang diperlukan ada di sana. Terima kasih.   -  person MITHU    schedule 11.05.2020
comment
BTW Anda dapat menggunakan "{:02}".format(7) untuk mendapatkan 07 alih-alih 7 dan kemudian Anda tidak perlu mencentang if len(str(page))==1: (BTW: sebagai gantinya if len(str(page))==1: Anda cukup mencentang if page < 10:)   -  person furas    schedule 11.05.2020
comment
ketika saya memeriksa payload.keys() dan membandingkan dengan kunci yang dikirim di browser web maka saya melihat kunci yang tidak dikirim oleh browser - yaitu. tombol untuk tombol bertanda panah (untuk berpindah ke halaman pertama/terakhir/sebelumnya/berikutnya) dan mungkin menimbulkan masalah. yaitu. dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl02 untuk tombol yang berpindah ke halaman pertama.   -  person furas    schedule 11.05.2020
comment
Saya menambahkan baris ini payload.pop('dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl02') di bagian bawah loop while untuk mengeluarkan kunci dari payload tetapi itu tampaknya tidak menyelesaikan masalah. Terima kasih.   -  person MITHU    schedule 11.05.2020
comment
tapi bisa banyak nama lain karena ada tombol lain yaitu. Saya melihat ...ctl28 untuk panah ke halaman berikutnya (tapi saya tidak yakin apakah itu tidak menggunakan nama yang berbeda jika halaman yang ditampilkan lebih sedikit). Saya tidak yakin tetapi halaman juga dapat menggunakan JavaScript untuk menghitung __EVENTVALIDATION dan server dapat memeriksanya - tetapi requests/bs4 tidak dapat menjalankan JavaScript.   -  person furas    schedule 11.05.2020
comment
@MITHU periksa jawaban di bawah ini   -  person αԋɱҽԃ αмєяιcαη    schedule 11.05.2020


Jawaban (2)


Ini mulai berfungsi jika saya menghapus kunci muatan seperti dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl02 yang merupakan kunci untuk tombol panah.

    name_length = len('dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl02')

    for key in list(payload.keys()):
        if key.startswith('dnn') and len(key) == name_length:
            payload.pop(key)
            print(key)

tetapi Anda dapat menggunakan metode dari αԋɱҽԃ αмєяιcαη jawaban untuk memastikan Anda hanya mengirimkan nilai yang diperlukan.


import requests
from bs4 import BeautifulSoup

link = 'https://www.icsi.in/student/Members/MemberSearch.aspx?SkinSrc=%5BG%5DSkins/IcsiTheme/IcsiIn-Bare&ContainerSrc=%5BG%5DContainers/IcsiTheme/NoContainer'

with requests.Session() as s:
    s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
    r = s.get(link)
    soup = BeautifulSoup(r.text,"lxml")

    payload = {i['name']:i.get('value','') for i in soup.select('input[name]')}
    payload['__EVENTTARGET'] = 'dnn$ctr410$MemberSearch$btnSearch'

    page = 5
    while True:

        r = s.post(link, data=payload)
        soup = BeautifulSoup(r.text, "lxml")
        for item in soup.select("span[id$='_lblFullName']"):
            print(item.text)

        page += 2

        payload = {i['name']:i.get('value','') for i in soup.select('input[name]')}
        payload['__EVENTTARGET'] = 'dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl{:02}'.format(page)

        name_length = len('dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl02')
        for key in list(payload.keys()):
            if key.startswith('dnn') and len(key) == name_length:
                payload.pop(key)
                print(key)

        payload['__dnnVariable'] = {'__scdoff':'1','__dnn_pageload':'__dnn_setScrollTop();'}
        payload['ScrollTop'] = '400'

EDIT: halaman menggunakan sistem yang lebih kompleks dan setelah 10 halaman menampilkan link baru tetapi dengan nilai lama ctl07, ctl09. Alih-alih tautan ini saya menggunakan nama dari tombol dengan panah ke halaman berikutnya - pada awalnya memiliki nilai ctrl28 tetapi setelah 10 halaman memiliki ctrl30 (karena ada lebih banyak tautan - ia menambahkan tautan ... ke daftar 10 halaman berikutnya/sebelumnya)

import requests
from bs4 import BeautifulSoup

link = 'https://www.icsi.in/student/Members/MemberSearch.aspx?SkinSrc=%5BG%5DSkins/IcsiTheme/IcsiIn-Bare&ContainerSrc=%5BG%5DContainers/IcsiTheme/NoContainer'

with requests.Session() as s:
    s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
    r = s.get(link)
    soup = BeautifulSoup(r.text,"lxml")

    payload = {i['name']:i.get('value','') for i in soup.select('input[name]')}
    payload['__EVENTTARGET'] = 'dnn$ctr410$MemberSearch$btnSearch'

    page = 1  # I don't need it to generate lins, now I use it only to display page number
    while True:
        print('page:', page)
        page += 1

        r = s.post(link, data=payload)
        soup = BeautifulSoup(r.text, "lxml")
        for item in soup.select("span[id$='_lblFullName']"):
            print(item.text)

        payload = {i['name']:i.get('value','') for i in soup.select('input[name]')}

        name_length = len('dnn$ctr410$MemberSearch$grdMembers$ctl00$ctl02$ctl01$ctl28')
        for key in list(payload.keys()):
            if key.startswith('dnn') and len(key) == name_length:
                payload.pop(key)
                #print(key)

        # button with arrow to next page

        next_page = soup.select("input[class='rgPageNext']")
        if not next_page:
            break

        next_page = next_page[0]['name']
        print(next_page)
        payload[next_page] = ''

        payload['__dnnVariable'] = {'__scdoff':'1','__dnn_pageload':'__dnn_setScrollTop();'}
        payload['ScrollTop'] = '400'
person furas    schedule 11.05.2020
comment
Setelah 12 atau 13 halaman skrip mulai menghasilkan hasil halaman sebelumnya berulang kali. - person MITHU; 11.05.2020
comment
apakah Anda memeriksanya di browser web? Mungkin itu menggunakan nilai yang berbeda dari yang Anda harapkan. Sekarang saya memeriksa tautan ke halaman 11 dan menggunakan lagi ctl07 alih-alih ctl25 - jadi cara kerjanya berbeda dari yang kita harapkan. - person furas; 11.05.2020
comment
alih-alih menghasilkan nilai untuk '__EVENTTARGET' saya menggunakan nama dari select("input[class='rgPageNext']")[0]['name'] (tombol dengan panah ke halaman berikutnya) dan kemudian saya mendapatkan nilai yang benar bahkan setelah 10 halaman. - person furas; 11.05.2020

Sebenarnya Anda perlu memasukkan parameter Payload postingan lengkap.

Kita harus melakukannya dalam Session yang sama menggunakan requests.Session() karena penomoran halaman situs web menggunakan rotasi function berdasarkan __dnnVariable yang mana server menerimanya berdasarkan permintaan JS yang diterjemahkan ke Loop.

Dimana sebenarnya arti Next

Jadi, saya telah membuat permintaan GET terlebih dahulu dan mengambil params yang diperlukan (beberapa di antaranya dinamis dan lainnya statis)

Kemudian, saya membuat permintaan posting di bawah session yang sama

import requests
import re
from bs4 import BeautifulSoup
from urllib.parse import unquote

data = {
    '__EVENTTARGET': "dnn$ctr410$MemberSearch$btnSearch",
    '__EVENTARGUMENT': '',
    '__VIEWSTATEENCRYPTED': '',
    'dnn$ctlHeader$dnnSearch$Search': 'SiteRadioButton',
    'dnn$ctlHeader$dnnSearch$txtSearch': '',
    'dnn$ctr410$MemberSearch$txtFirstName': '',
    'dnn$ctr410$MemberSearch$txtLastName': '',
    'dnn$ctr410$MemberSearch$ddlMemberType': 0,
    'dnn$ctr410$MemberSearch$txtMembershipNumber': '',
    'dnn$ctr410$MemberSearch$txtCpNumber': '',
    'dnn$ctr410$MemberSearch$txtCity': '',
    'dnn$ctr410$MemberSearch$txtOrganisation': '',
    'dnn$ctr410$MemberSearch$txtAddress2': '',
    'dnn$ctr410$MemberSearch$txtAddress3': '',
    'dnn$ctr410$MemberSearch$txtEmail': '',
    'dnn_ctr410_MemberSearch_grdMembers_ClientState': '',
    'ScrollTop': 432,
    '__dnnVariable': '{"__scdoff":"1","__dnn_pageload":"__dnn_setScrollTop();"}'
}


def main(url):
    with requests.Session() as req:
        r = req.get(url)
        soup = BeautifulSoup(r.content, 'html.parser')
        data['StylesheetManager_TSSM'] = re.search(
            r"hf.value \+= '(.*?)\'", r.text).group(1)
        data['ScriptManager_TSM'] = unquote(soup.findAll('script', src=True)
                                            [2]['src']).split("=", 3)[-1]
        data['__VIEWSTATE'] = soup.find("input", id="__VIEWSTATE").get("value")
        data['__VIEWSTATEGENERATOR'] = soup.find(
            "input", id="__VIEWSTATEGENERATOR").get("value")
        data['__EVENTVALIDATION'] = soup.find(
            "input", id="__EVENTVALIDATION").get("value")

        for _ in range(10):
            r = req.post(url, data=data)
            soup = BeautifulSoup(r.content, 'html.parser')
            names = [name.text for name in soup.select("div.name_head")]
            page = soup.select_one(
                "a.rgCurrentPage").next_sibling['href'].split("'")[1]
            data['__EVENTTARGET'] = page
            data['__EVENTVALIDATION'] = soup.find(
                "input", id="__EVENTVALIDATION").get("value")
            data['__VIEWSTATE'] = soup.find(
                "input", id="__VIEWSTATE").get("value")
            print(names)


main("https://www.icsi.in/student/Members/MemberSearch.aspx")

Catatan: pada setiap permintaan Anda akan mendapatkan data yang tidak berurutan karena fungsi search menggunakan random di server back-end.

Keluaran:

['SH. DILIP RAGHUNATH KOTWAL', 'SH. ARUNODAY ROY MUKHERJEE', 'SH. J SUBRAMANI', 'SH. R KRISHNAMANI', 'SH. R NARAYANASWAMI', 'SH. M V GOPALAKRISHNAN', 'SH. RAJAM KRISHNAMURTHY', 'SH. V SIVASUBRAMANIAN', 'SH. V RAGHAVENDRAN', 'SH. G V AIMAN']
['SH. K J MATHEW', 'SH. K K GHOSH', 'SH. SUBHASH CHANDER DHAWAN', 'SH. BABU RAM MAHESWARI', 'SH. S SWAMINATHAN', 'SH. T S A AIYER', 'SH. KOVILOOR VIJAYARAGHAVACHARI SAMPATHKUMAR', 'SH. M KRISHNAN', 'SH. R N BANSAL', 'SH. N V RAMAN']
['SH. R VENKATARAMANI', 'SH. UTPALENDU ROY CHOUDHURY', 'SH. LAKSHMI NARAYANAN V', 'SH. PARIJAT KUMAR HORE', 'SH. B R VENKATESAN', 'SH. KISHAN GOPAL SOMANI', 'SH. O P GANERIWALA', 'SH. P T KUPPUSWAMY', 'SH. U P MATHUR', 'SH. N N UPADHYAY']
['SH. N K BHANDARI', 'SH. S R C SETTY', 'SH. S V BALASUBRAMANIAN', 'SH. HOSHIE HIRJI MALGHAM', 'SH. KAIKOBAD SORABJI ITALIA', 'SH. K SIVADAS', 'SH. K K SIVARAMAKRISHNAN', 'SH. A CHANDRASEKARAN', 'SH. R PONNAMBALAM', 'SH. T K B VENKATARAMAN']
['SH. NARINDER PAL', 'SH. PARKASH ATAM', 'SH. K A PARTHASARATHY', 'SH. SURESH CHANDRA OSWAL', 'SH. MAHENDRA KANTILAL SHAH', 'SH. V. SANTHANAKRISHNA', 'SH. VASANT NARAYAN GOGATE', 'SH. MANEKLAL 
PATEL', 'SH. B N VISHWANATH', 'SH. B S L NARAYAN']
['SH. P L N VIJAYANAGAR', 'SH. SHREEPAD MARTAND  KORDE', 'SH. SHIV BHAGWAN KOTHARI', 'SH. R B POPLAI', 'SH. RAMESH KHANNA', 'SH. RAVINDER NATH JOSHI', 'SH. VIDYA SAGAR AGGARWAL', 'SH. ARVIND JAYKUMAR CHAKOTE', 'SH. V RAMASESHAN', 'SH. BADRINARAYAN BALDAWA']
['SH. C GOVINDANKUTTY', 'SH. A G MADHAVAN', 'SH. DHIRAJ NATH BHATTACHARYYA', 'SH. RAMESHWAR LAL INANI', 'SH. RAMESHWARDAS C DAGA', 'SH. R SUBRAMANIAN', 'SH. S M REGE', 'SH. NARENDRA KUMAR KAPOOR', 'SH. K RAMAMURTHI', 'SH. ROOPENDRA NARAYAN ROY']
['SH. KALYAN KUMAR MITRA', 'SH. KALYANASUNDARAM ', 'SH. N A SESHADRI', 'SH. RAJENDRA KUMAR JAIN', 'SH. BISWAJIT SEN', 'SH. RAMKRISHNA NATHOOMAL  AGRAWAL', 'SH. P C SHETH', 'SH. K S NATARAJAN', 
'SH. S N DAMLE', 'SH. A M FADIA']
['DR. K N M RAO', 'SH. IYER M. RAMASWAMY', 'SH. DILIP KANTI MAZUMDAR', 'SH. RAM CHANDRA NIGAM', 'SH. SUBRAHMANIAM VISWANATHAN', 'SH. SURESH KUMAR JERATH', 'SH. A Y SRINIVASAN', 'DR. S C GARG', 
'SH. CHANDRA PRAKASH SHARDA', 'SH. M P JAIN']
['SH. E S DWARKANATH', 'SH. MYSORE SHAMANNA  RAMACHANDRA', 'SH. SUBHASH CHANDER SINGHAL', 'SH. T T SINHA', 'SH. G R BHANDARI', 'SH. M P GOEL', 'SH. CHOKKANATHAPURAM SUBRAMANIAN  NATESAN', 'SH. 
V M PATEL', 'SH. BIJOY KUMAR AGARWALLA', 'SH. BAHADUR CHAND JAIN']
person αԋɱҽԃ αмєяιcαη    schedule 11.05.2020
comment
Ya, kedua solusi Anda berhasil. Terima kasih satu triliun. - person MITHU; 11.05.2020
comment
@MITHU sama-sama, silakan terima jawaban saya dengan mencentang tanda centang di samping jawaban jika itu membantu Anda. Anda juga dapat memberi suara positif jika Anda menyukainya. - person αԋɱҽԃ αмєяιcαη; 11.05.2020