从存在于 HTML 文件中的 JavaScript 代码中抓取数据
Scraping data from a JavaScript code that is present inside an HTML file
我正在使用 scrapy(Python) 从 http://www.heteropharmacy.com/outlets.html 中抓取所有地址。 City/Town 下拉列表包含许多城市。每当我 select 一个城市时,就会显示新地址。
但是,没有向服务器发出请求。我同时使用了 firebug Lite 和 Chrome 中的开发人员工具。没有向服务器发出 POST/GET 个请求。
当我查看源代码时,我发现:
<script src="jScript/myScript.js" type="text/javascript"></script>
单击 "jScript/myScript.js" 时,我被重定向到 http://www.heteropharmacy.com/jScript/myScript.js。这个源代码是一个javascript文件,在下拉框中包含了所有城市的所有地址。这些地址在一个数组中。
我的问题是如何获取此 javascript 代码的 html 代码,以便我可以使用 scrapy 提取它。或者我可以直接从 javascript file.I 提取所有可能的解决方案并且我愿意使用任何 API 而不仅仅是 Scrapy.
我在网上查了很多,也只能找到对服务器有请求的情况的解决方法。
我会提取 Javascript 代码并使用一些库来执行 JS 代码并从那里检索结果,因为正如我所见,代码将生成一个您可以提取的 JS 数组。
也许 运行 Python 中的 JS 代码库可以提供帮助
https://pypi.python.org/pypi/PyExecJS
最好的方法是使用 BeautifulSoup。首先,将原始 myScript.js 文件转换为 HTML。您可以使用此 HTML 文件创建汤。
创建汤后,使用正则表达式提取所需的数据。
假设您的 HTML 在 html_doc
html_code = html_doc.encode('utf-8')
soup = BeautifulSoup(html_code)
script = soup.find_all("script")
'script' 将包含可以使用正则表达式解析的 javascript 文件的字符串。希望这可以帮助。
您还可以使用 urllib2 提取此数据,然后执行正则表达式。这可能有点混乱,但有效。
import urllib2
import re
url = 'http://www.heteropharmacy.com/jScript/myScript.js'
data = urllib2.urlopen(url).read()
add_data = re.findall('new Array(.*?)\);', data, re.MULTILINE|re.DOTALL)
以上代码会将javascript文件中的所有数组放入add_data
列表中。您可以再次使用 re 来获取地址。对于前。下面一行为您提供了所有海得拉巴地址。这可以根据您的要求进行优化
hyd_adds = re.findall('"(.*?)"', add_data[2])
这里有多个选项:
- 使用正则表达式直接从javascript
中提取数据
- 使用 javascript 解析器 直接从 javascript 中提取数据(例如
slimit
- example here)
- 使用
ScrapyJS
package with Splash
渲染javascript
- 让 真正的浏览器在
selenium
的帮助下执行 javascript - 浏览器可以是无头的(比如 PhantomJS)
如果您选择使用正则表达式,可以通过以下方式制作州字典 -> 药店列表:
from pprint import pprint
import re
import requests
url = 'http://www.heteropharmacy.com/jScript/myScript.js'
with requests.Session() as session:
response = session.get(url)
pattern = re.compile(r"states_arr\['(\w+)'\]= new Array\((.*?)\);", re.MULTILINE | re.DOTALL)
results = {state: [item.strip()[1:] for item in pharmacies.split('",')]
for state, pharmacies in pattern.findall(response.content)}
pprint(results)
打印:
{'Chennai': ['Adambakkam # 044 22530209 # Opp. Murugan Temple, ; Brindavan Nager, ; Mohanpuri - 5th Street, ; Adambakkam, Chennai \x96 600 088',
'Adambakkam - 2 # 044 - 22553195, 64540549 # No. 2 B, Ground Floor, Ganesh Nagar Main Road, ; Near NGO Colony Bus Stop, Telephone Colony, ; Adambakkam, Chennai - 600088.',
'Allapakkam # 044- 64520024 # New No.131, Old No.10 M, ; Shop No. F, Alapakkam Main Road, ; Near Jeva Complex, Alapakkam, Chennai-16.',
'Anna nagar # 044-26220891 # New No.1, AI Block, Second Street, ; Near Anna Adarsh College for Women, ; Shanthi Colony, Anna Nagar, ; Chennai- 600040.',
...
'Visakhapatnam': ['Adarsh Nagar # 9247001943 # H. No. 3-352, Beside Andhra Bank, ; Near Manapuram Finance Ltd. Adarsha Nagar, ; Old Dairy Form, Visakhapatnam',
'B.C. Road, Gajuwaka # 0891 2546005 # D. No.13-6-14/1, ; Opp. Dr. T. Dhanalatha Hospital, ; B. C. Road, Gajuwaka, Visakhapatnam.',
'Chinawaltair # 0891-2546001, 6464501 # D.No: 6-5-3, Opp. Jaganadh Temple, ; China Waltair, Visakapatnam-17.',
'Marripalem # 9247000573 # D. No. 38-40-70, Opp. Ramalingeswara Alayam, ; Marripalem Main Road, ; Marripalem, Visakhapatnam.',
'Muralinagar # 0891-6464507# D.No.39-8-9/5, ; Varma Complex, 48th Bus stop, ; Murali Nagar, Visakhapatnam',
'NRI Hospital # 0891-2714453, 6464506 # 50-27-16, Rammahon Chamber, ; Near NRI Hospital, ; Seethammadhara, Visakapatnam.',
'Pedawaltair # 0891-2546006 # H.No.8-1-97/2/2, ; Near Vishaka Eye Hospital, ; Pedawaltair junction, Vizag.',
'Ramnagar # 0891-2546002, 6464502 # D.No. 10-50-11/2, 1st Floor, ; Beside Care Hospital, Main Road, ; Ramnagar, Visakapatnam.',
'Seetammadhara # 0891-2713706, 6464504 # H.No: 55-14-109/1, ; Beside Sri Sivaramareddy Sweets, ; Opp to E- Seva kendram, ; Seetammadhara, Visakhapatnam."']}
我正在使用 scrapy(Python) 从 http://www.heteropharmacy.com/outlets.html 中抓取所有地址。 City/Town 下拉列表包含许多城市。每当我 select 一个城市时,就会显示新地址。
但是,没有向服务器发出请求。我同时使用了 firebug Lite 和 Chrome 中的开发人员工具。没有向服务器发出 POST/GET 个请求。
当我查看源代码时,我发现:
<script src="jScript/myScript.js" type="text/javascript"></script>
单击 "jScript/myScript.js" 时,我被重定向到 http://www.heteropharmacy.com/jScript/myScript.js。这个源代码是一个javascript文件,在下拉框中包含了所有城市的所有地址。这些地址在一个数组中。
我的问题是如何获取此 javascript 代码的 html 代码,以便我可以使用 scrapy 提取它。或者我可以直接从 javascript file.I 提取所有可能的解决方案并且我愿意使用任何 API 而不仅仅是 Scrapy.
我在网上查了很多,也只能找到对服务器有请求的情况的解决方法。
我会提取 Javascript 代码并使用一些库来执行 JS 代码并从那里检索结果,因为正如我所见,代码将生成一个您可以提取的 JS 数组。
也许 运行 Python 中的 JS 代码库可以提供帮助 https://pypi.python.org/pypi/PyExecJS
最好的方法是使用 BeautifulSoup。首先,将原始 myScript.js 文件转换为 HTML。您可以使用此 HTML 文件创建汤。
创建汤后,使用正则表达式提取所需的数据。 假设您的 HTML 在 html_doc
html_code = html_doc.encode('utf-8')
soup = BeautifulSoup(html_code)
script = soup.find_all("script")
'script' 将包含可以使用正则表达式解析的 javascript 文件的字符串。希望这可以帮助。
您还可以使用 urllib2 提取此数据,然后执行正则表达式。这可能有点混乱,但有效。
import urllib2
import re
url = 'http://www.heteropharmacy.com/jScript/myScript.js'
data = urllib2.urlopen(url).read()
add_data = re.findall('new Array(.*?)\);', data, re.MULTILINE|re.DOTALL)
以上代码会将javascript文件中的所有数组放入add_data
列表中。您可以再次使用 re 来获取地址。对于前。下面一行为您提供了所有海得拉巴地址。这可以根据您的要求进行优化
hyd_adds = re.findall('"(.*?)"', add_data[2])
这里有多个选项:
- 使用正则表达式直接从javascript 中提取数据
- 使用 javascript 解析器 直接从 javascript 中提取数据(例如
slimit
- example here) - 使用
ScrapyJS
package withSplash
渲染javascript - 让 真正的浏览器在
selenium
的帮助下执行 javascript - 浏览器可以是无头的(比如 PhantomJS)
如果您选择使用正则表达式,可以通过以下方式制作州字典 -> 药店列表:
from pprint import pprint
import re
import requests
url = 'http://www.heteropharmacy.com/jScript/myScript.js'
with requests.Session() as session:
response = session.get(url)
pattern = re.compile(r"states_arr\['(\w+)'\]= new Array\((.*?)\);", re.MULTILINE | re.DOTALL)
results = {state: [item.strip()[1:] for item in pharmacies.split('",')]
for state, pharmacies in pattern.findall(response.content)}
pprint(results)
打印:
{'Chennai': ['Adambakkam # 044 22530209 # Opp. Murugan Temple, ; Brindavan Nager, ; Mohanpuri - 5th Street, ; Adambakkam, Chennai \x96 600 088',
'Adambakkam - 2 # 044 - 22553195, 64540549 # No. 2 B, Ground Floor, Ganesh Nagar Main Road, ; Near NGO Colony Bus Stop, Telephone Colony, ; Adambakkam, Chennai - 600088.',
'Allapakkam # 044- 64520024 # New No.131, Old No.10 M, ; Shop No. F, Alapakkam Main Road, ; Near Jeva Complex, Alapakkam, Chennai-16.',
'Anna nagar # 044-26220891 # New No.1, AI Block, Second Street, ; Near Anna Adarsh College for Women, ; Shanthi Colony, Anna Nagar, ; Chennai- 600040.',
...
'Visakhapatnam': ['Adarsh Nagar # 9247001943 # H. No. 3-352, Beside Andhra Bank, ; Near Manapuram Finance Ltd. Adarsha Nagar, ; Old Dairy Form, Visakhapatnam',
'B.C. Road, Gajuwaka # 0891 2546005 # D. No.13-6-14/1, ; Opp. Dr. T. Dhanalatha Hospital, ; B. C. Road, Gajuwaka, Visakhapatnam.',
'Chinawaltair # 0891-2546001, 6464501 # D.No: 6-5-3, Opp. Jaganadh Temple, ; China Waltair, Visakapatnam-17.',
'Marripalem # 9247000573 # D. No. 38-40-70, Opp. Ramalingeswara Alayam, ; Marripalem Main Road, ; Marripalem, Visakhapatnam.',
'Muralinagar # 0891-6464507# D.No.39-8-9/5, ; Varma Complex, 48th Bus stop, ; Murali Nagar, Visakhapatnam',
'NRI Hospital # 0891-2714453, 6464506 # 50-27-16, Rammahon Chamber, ; Near NRI Hospital, ; Seethammadhara, Visakapatnam.',
'Pedawaltair # 0891-2546006 # H.No.8-1-97/2/2, ; Near Vishaka Eye Hospital, ; Pedawaltair junction, Vizag.',
'Ramnagar # 0891-2546002, 6464502 # D.No. 10-50-11/2, 1st Floor, ; Beside Care Hospital, Main Road, ; Ramnagar, Visakapatnam.',
'Seetammadhara # 0891-2713706, 6464504 # H.No: 55-14-109/1, ; Beside Sri Sivaramareddy Sweets, ; Opp to E- Seva kendram, ; Seetammadhara, Visakhapatnam."']}